package com.yunji.storage.business;

import com.yunji.base.enums.SystemName;
import com.yunji.common.base.BaseBusiness;
import com.yunji.common.constant.LogicCode;
import com.yunji.common.enums.business.StorageStatus;
import com.yunji.common.enums.business.StorageType;
import com.yunji.common.enums.common.ErrorEnum;
import com.yunji.common.utils.DecimalUtils;
import com.yunji.common.utils.TimeUtils;
import com.yunji.common.utils.bean.BeanUtils;
import com.yunji.common.utils.uuid.UUIDUtils;
import com.yunji.storage.bo.StockSelectQueryBO;
import com.yunji.storage.consumer.StockConsumer;
import com.yunji.storage.domain.*;
import com.yunji.storage.dto.StockDTO;
import com.yunji.storage.dto.StorageOperateDTO;
import com.yunji.storage.enums.DeletableStatus;
import com.yunji.storage.enums.StorageBusinessType;
import com.yunji.storage.provide.StockProvide;
import com.yunji.storage.service.IStockService;
import com.yunji.storage.service.IStorageRecordsService;
import com.yunji.storage.service.IStorageTicketService;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @Project: yunji-coffee
 * @Package: com.yunji.storage.business
 * @Title: StorageBusiness
 * <p>
 * History:
 * Date                     Version     Author          Summary
 * ============================================================
 * 2024-08-29 13:58:42      V1.0        HuaAo       库存操作通用Business
 */
@Component
public class StorageBusiness extends BaseBusiness {

    @Resource
    IStorageTicketService storageTicketService;

    @Resource
    IStorageRecordsService storageRecordsService;

    @Resource
    StorageInteractBusiness interactBusiness;

    @Resource
    IStockService stockService;

    @Resource
    StockConsumer stockConsumer;

    @Resource
    StockProvide stockProvide;


    /**
     * 检查报废库存
     *
     * @param info
     */
    public void checkDiscardStock(DiscardTicketDO discardTicket, DiscardInfoDO info) {
        Long belongId = discardTicket.getOutBelongId();
        Long productId = info.getProductId();
        BigDecimal discardAmount = info.getDiscardAmount();

        StockDO vo = stockService.select(new StockSelectQueryBO(belongId, productId));
        Assert.isTrue(BeanUtils.isNotNull(vo), ErrorEnum.BUSINESS_812003.getText());

        BigDecimal usableStock = vo.getUsableStock();
        logs.info("【商品库存】{}商品：报废库存{},可用库存{}", info.getProductName(), discardAmount, usableStock);

        Assert.isTrue(!DecimalUtils.more(discardAmount, usableStock), ErrorEnum.BUSINESS_812003.getText());

        Integer stockStatus = stockConsumer.getStockStatus(belongId);
        if (Objects.equals(LogicCode.YES, stockStatus)) {
            StockDO stock = new StockDO();
            stock.setBelongId(belongId);
            stock.setProductId(info.getProductId());
            stock.setDisableStock(info.getDiscardAmount());
            stock.setUsableStock(info.getDiscardAmount().negate());
            stock.setAllStock(BigDecimal.ZERO);
            stock.setFrozenStock(BigDecimal.ZERO);
            List<StockDO> list = new ArrayList<>();
            list.add(stock);
            stockProvide.handleStock(list);
        }
    }

    /**
     * 处理报废出库单据
     */
    public void handleDiscardStorageTicket(DiscardTicketDO discardTicket, List<DiscardInfoDO> infoList) {

        StorageTicketDO storageTicket = new StorageTicketDO();
        List<StorageRecordsDO> recordsList = new ArrayList<>();

        Long discardId = discardTicket.getDiscardId();
        logs.info("【处理出入库单据】业务ID:{}", discardId);

        String discardCode = discardTicket.getDiscardCode();
        logs.info("【处理出入库单据】业务单号:{}", discardCode);

        Integer businessType = StorageBusinessType.DISCARD_BUSINESS.getCode();
        logs.info("【处理出入库单据】业务类型:{}", businessType);

        //库存操作参数
        StorageOperateDTO operateDTO = new StorageOperateDTO();
        List<StockDTO> dtoList = new ArrayList<>();

        storageTicket.setBusinessId(discardId);
        storageTicket.setBusinessCode(discardCode);
        storageTicket.setBusinessType(businessType);
        storageTicket.setStorageType(StorageType.OUT_STORAGE.getCode());
        storageTicket.setDeletable(DeletableStatus.CAN_NOT.getCode());

        String ticketCode = UUIDUtils.outStorageCode();
        logs.info("【处理出入库单据】出库据Code:{}", ticketCode);

        Long outBelongId = discardTicket.getOutBelongId();
        logs.info("【处理出入库单据】出库单位:{}", outBelongId);

        operateDTO.setBelongId(outBelongId);
        operateDTO.setStorageType(StorageType.OUT_STORAGE.getCode());
        operateDTO.setBusinessType(StorageBusinessType.DISCARD_BUSINESS.getCode());
        operateDTO.setBusinessCode(discardCode);

        storageTicket.setOperateTime(TimeUtils.getNowDate());
        storageTicket.setOperateName(SystemName.ENABLED.getText());
        storageTicket.setTicketCode(ticketCode);
        storageTicket.setStorageStatus(StorageStatus.ALREADY_STORAGE.getCode());
        storageTicket.setBelongId(outBelongId);


        logs.info("【处理出入库单据】出入库单据信息:{}", storageTicket);
        Assert.isTrue(storageTicketService.create(storageTicket), "新增失败");

        for (DiscardInfoDO info : infoList) {
            StorageRecordsDO storageRecords = new StorageRecordsDO();

            BeanUtils.clone(info, storageRecords);
            BeanUtils.clone(storageTicket, storageRecords);

            BigDecimal discardAmount = info.getDiscardAmount();
            logs.info("【处理出入库单据】报废数量:{}", discardAmount);
            storageRecords.setExpectQuantity(discardAmount);

            storageRecords.setActualQuantity(discardAmount);
            storageRecords.setOperateTime(TimeUtils.getNowDate());

            StockDTO stockDTO = new StockDTO();
            stockDTO.setProductId(info.getProductId());
            stockDTO.setActualQuantity(discardAmount);

            recordsList.add(storageRecords);
            dtoList.add(stockDTO);

        }

        logs.info("【处理出入库单据】出入库记录:{}", recordsList);
        for (StorageRecordsDO storageRecords : recordsList) {
            Assert.isTrue(storageRecordsService.create(storageRecords), "新增失败");
        }

        operateDTO.setList(dtoList);
        interactBusiness.operateStorage(operateDTO);
    }
}